/*
 * Vect4.h
 *
 *  Created on: 29 août 2010
 *      Author: seeme
 *      Des vecteurs de 4 quelquchoses.
 *      on peut les normaliser, faire leur produit vectoriel (*)
 *      ou leur produit scalaire (^)
 */

#ifndef VECT4_H_
#define VECT4_H_

#include <ostream>
#include <iostream>
#include <cmath>
#include <vector>


//Template vector
//
template <typename T> class Vect4{

	public:
		T x, y, z, w;
		Vect4<T>(T a, T b, T c){x = a; y = b; z = c; w = 1;}
		Vect4<T>(T a, T b, T c, T d){x = a; y = b; z = c; w = d;}

		Vect4<T>():x(), y(), z(), w(1){}

		Vect4<T>(std::vector<T> arg){
			if(arg.size() < 3)
				return;
			x = arg[0];
			y = arg[1];
			z = arg[2];

			w = 1;

			if(arg.size() > 3)
				w = arg[3];
		}

		friend std::ostream& operator<<(std::ostream& out, const Vect4<T>& v){
			v.print(out);
			return out;
		}


		//Norme
		float norm(){
			return sqrt(x*x + y*y + z*z + w*w);
		}

		//dot product
		T operator^(const Vect4<T>& v){
			return x*v.x + y*v.y + z*v.z + w*v.w;
		}

		float* asArray(){
			float *array = new float[4];
			array[0] = x;
			array[1] = y;
			array[2] = z;
			array[3] = w;
			return array;
		}

		//Norm = 1
		Vect4<T>& normalize(){
			float n = norm();
			if(n != 0){
				x /= n;
				y /= n;
				z /= n;
				w /= w;
			}
			return *this;
		}

		virtual void print(std::ostream& o) const {
			o << "Vect(" << x << "," << y<< "," << z<< "," << w << ")";
		}

		Vect4<T>& operator=(int a){
			x = a;
			y = a;
			z = a;
			w = a;
			return *this;
		}

		Vect4<T>& operator=(const Vect4<T>& v){
			if(this != &v){
				x = v.x;
				y = v.y;
				z = v.z;
				w = v.w;
			}
			return *this;
		}
};

template <typename T>
Vect4<T> operator*(float k, const Vect4<T>& v){
	return Vect4<T>(v.x*k, v.y*k, v.z*k, v.w*k);
}

template <typename T>
Vect4<T> operator*(const Vect4<T>& v, float k){
	return k*v;
}

template <typename T>
bool operator==(const Vect4<T>&v1, const Vect4<T>& v2){
	return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w;
}

template <typename T>
bool operator!=(const Vect4<T>& v1, const Vect4<T>& v2){
			return !(v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w);
}

template <typename T>
const Vect4<T> operator*(const Vect4<T>& v1, const Vect4<T>& v){
	return Vect4<T>(v1.y*v.z-v1.z*v.y, v1.z*v.w-v1.w*v.z, v1.w*v.x-v1.x*v.w, v1.x*v.y-v1.y*v.x);
}

template <typename T>
const Vect4<T> operator-(const Vect4<T>& v1, const Vect4<T>& v){
	return Vect4<T>(v1.x-v.x, v1.y-v.y, v1.z-v.z, v1.w-v.w);
}

template <typename T>
const Vect4<T> operator+(const Vect4<T>& v1, const Vect4<T>& v){
	return Vect4<T>(v1.x+v.x, v1.y+v.y, v1.z+v.z, v1.w+v.w);
}


#endif /* VECT4_H_ */
